package ferp.core.ai.filter;

import ferp.core.ai.tree2.Evaluator;
import ferp.core.card.Card;
import ferp.core.game.Trick;
import ferp.core.player.Hand;

/**
 * User: olegs
 * Date: 2/16/13 4:32 PM
 */
public class FilterWhisterAfterDeclarerMove
{
  public static int apply(Evaluator evaluator, int candidates, int player, int trick, Card.Suit trump, int hand, int declarer)
  {
    int filtered = 0;
    Card lbc = getLowestBeatCard(evaluator, trick, candidates, player, hand, trump);
    int lc = FilterWhisterAfterDeclarerMoveOpen.getLowestCandidates(candidates);

    switch (hand)
    {
      // hand 1 means first move was made by declarer
      case 1:
        if (lbc == null)
          filtered = lc;
        else
        {
          filtered = lbc.hash;

          // get declarer's card
          Card highest = Trick.highest(trick, trump);

          // add lowest candidates only if rank difference is greater than 1,
          // otherwise partner couldn't have lower beat card than current player
          if (highest.suit != lbc.suit || lbc.rank.ordinal() - highest.rank.ordinal() > 1)
            filtered = Hand.add(filtered, lc);
        }
        break;

      case 2:
        // the player should not "beat" his partner's card
        filtered = (Trick.winner(trick, trump) != declarer || lbc == null) ? lc : lbc.hash;
        break;

    }

    return filtered == 0 ? candidates : filtered;
  }

  private static Card getLowestBeatCard(Evaluator evaluator, int trick, int candidates, int player, int hand, Card.Suit trump)
  {
    Card lowest = null;

    for (int h = evaluator.start(candidates); h != 0; h = evaluator.next(candidates, h))
    {
      Card c = Card.card(h);

      trick = Trick.add(trick, player, c.compressed);

      if (Trick.winner(trick, trump) == player && (lowest == null || c.rank.ordinal() < lowest.rank.ordinal()))
        lowest = c;

      trick = Trick.pop(trick);
    }

    return lowest;
  }
}
